import { Component, OnInit, Input, AfterViewInit, OnChanges, ViewChild, ElementRef, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { getCertainNumDecimalNumberReg, onlyNumberReg } from 'app/utils/contraints'
import { NzInputNumberComponent } from 'ng-zorro-antd'

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CustomNumberInputComponent),
  multi: true,
}

@Component({
  selector: 'app-custom-number-input',
  templateUrl: './custom-number-input.component.html',
  styleUrls: ['./custom-number-input.component.less'],
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],
})
export class CustomNumberInputComponent implements OnInit, ControlValueAccessor, AfterViewInit, OnChanges {
  /** 小数位数 */
  @Input() precision: number

  /** 后缀 */
  @Input() addOnAfter: string

  /** 最小值 */
  @Input() min = 0

  /** 最大值 */
  @Input() max = Infinity

  /** disable */
  @Input() disabled = false

  /** 步长 */
  step: number

  @ViewChild('input') inputRef: NzInputNumberComponent

  private innerValue: number

  propagateChange = (_: any) => {}

  writeValue(value: any): void {
    this.innerValue = value
  }

  registerOnChange(fn: any): void {
    this.propagateChange = fn
  }

  registerOnTouched(fn: any): void {}

  setDisabledState?(isDisabled: boolean): void {}

  get value(): any {
    return this.innerValue
  }

  set value(v: any) {
    if (v !== this.innerValue) {
      this.innerValue = v
    }
  }

  constructor() {}

  ngOnInit() {
    this.setStep()
  }

  ngAfterViewInit() {}

  ngOnChanges() {}

  onInput(event: any) {
    const value = event.target.value
    this.setValue(value)

    if (this.innerValue <= this.max) {
      this.inputRef.setValue(this.innerValue, true)
    } else {
      this.setValue(this.max)
    }
  }

  onChange(value: number) {
    this.setValue(value)
  }

  private setStep(): void {
    this.step = this.precision === 2 ? 0.01 : 1
  }

  private parseAsNumber(value: string) {
    if (!this.precision || this.precision === 0) {
      /** 整数 */
      if (onlyNumberReg.test(value.toString())) {
        this.setValue(parseInt(value, 10))
        return
      }
    } else {
      /** 指定小数位数 */
      const reg = getCertainNumDecimalNumberReg(this.precision)
      if (reg.test(value.toString())) {
        this.setValue(parseFloat(value))
        return
      }
    }
    return false
  }
  private setValue(value: number): void {
    this.innerValue = value
    this.propagateChange(this.innerValue)
  }
}
